home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1993 by NeXT Computer, Inc as an unpublished work.
- * All rights reserved.
- *
- * QVisionSetMode.m -- Mode support for the QVision.
- *
- * NOTE: view this file with tabs set to 4 spaces
- *
- * Author: Derek B Clegg 21 May 1993
- * Based on work by Joe Pasqua.
- * Tue Aug 16 16:53:03 PDT 1994 James C. Lee
- * Add 3.3 bus support & 8-bit color support.
- * Thu Sep 22 16:39:18 PDT 1994 James C. Lee
- * Use the new PCI API that returns IOReturn instead of BOOL.
- */
- #import <string.h>
- #import <driverkit/generalFuncs.h>
- #import <driverkit/i386/ioPorts.h>
- #import <driverkit/i386/directDevice.h>
- #import <driverkit/i386/IOPCIDeviceDescription.h>
- #import <driverkit/i386/IOPCIDirectDevice.h>
- #import <string.h>
- #import <stdio.h>
- //#import <stdlib.h>
-
- #import "QVision.h"
-
-
- /* private interfaces for SetMode category of QVision */
- /*@interface QVision (SetMode_Private)
- - (ConfigBusType) determineConfigBusType;
- - (QVAdapterType) determineVLCardType;
- - (QVAdapterType) determinePCICardType;
- - (QVAdapterType) determineEISACardType;
- @end
- */
- /* The `SetMode' category of `QVision'. */
-
- @implementation QVision (SetMode)
-
- - (ConfigBusType) determineConfigBusType
- {
- const char *busTypeName;
- IOConfigTable *configTable;
-
- configTable = [[self deviceDescription] configTable];
- busTypeName = [configTable valueForStringKey:"Bus Type"];
- if (strcmp(busTypeName, "PCI")==0) {
- busType = BusPCI;
- } else if (strcmp(busTypeName, "EISA")==0) {
- busType = BusEISA;
- } else {
- /* default to ISA or VL */
- busType = BusISAorVL;
- }
- return busType;
- }
-
- /* assume dac type is determined already. This method is called by
- * determineConfiguration only */
- - (QVAdapterType) determineVLCardType
- {
- QVAdapterType adapterType;
-
- adapterType = UnknownAdapter;
- switch (dac) {
- case Bt484:
- adapterType = OrionAdapter;
- break;
- case Bt485:
- case Bt485A:
- case ATT20C505:
- adapterType = Orion12Adapter;
- break;
- default:
- break;
- }
- return adapterType;
- }
-
- /* TODO: clean up error handling, i.e. return something meaningful rather
- * than returning [super free]; */
- - (QVAdapterType) determinePCICardType
- {
- unsigned int physicalAddress;
- int numRanges;
- IOPCIConfigSpace configSpace;
- unsigned char devNum, funcNum, busNum;
- unsigned long vendorDeviceID;
- unsigned short vendorID, deviceID;
- char idString[11];
- id deviceDescription;
- QVAdapterType adapterType;
- IOConfigTable *configTable;
- IORange *oldRange, newRange[3];
-
- adapterType = UnknownAdapter;
- if (![self isPCIPresent]) {
- IOLog ("%s: No PCI card found.\n", [self name]);
- return UnknownAdapter;
- }
- deviceDescription = [self deviceDescription];
- [deviceDescription getPCIdevice:&devNum function:&funcNum bus:&busNum];
- IOLog_dbg(("%s: PCI Dev:%d Func:%d Bus:%d\n", [self name], devNum,
- funcNum, busNum));
- [self getPCIConfigData:&vendorDeviceID atRegister:0x00];
- vendorID = (unsigned short) vendorDeviceID;
- deviceID = (unsigned short) (vendorDeviceID >> 16);
- IOLog("%s: vendorID=%04x deviceID=%04x\n", [self name], vendorID,
- deviceID);
-
- /* go through "Auto Detect IDs" and make sure we are okay */
- configTable = [[self deviceDescription] configTable];
- sprintf(idString, "%08lx", vendorDeviceID);
- if (strstr([configTable valueForStringKey:"Auto Detect IDs"], idString)
- == NULL)
- {
- IOLog("%s: VenderDeviceID %08lx not found in instance table.\n",
- [self name], vendorDeviceID);
- return UnknownAdapter;
- } else {
- /* add more card types here if there are PCI cards other than 1280P
- * actually, if there are more than one PCI cards, we should determine
- * which PCI card here */
- adapterType = QVision1280P;
- }
-
- /* need to do set framebuffer address for PCI */
- [self getPCIConfigSpace:&configSpace];
- physicalAddress = configSpace.BaseAddress[0];
- physicalAddress &= 0xfffffff0; /* mask out lower 4 bits */
-
- if (physicalAddress) {
- IOLog_dbg(("%s: try to set physical address to 0x%08x\n",
- [self name], physicalAddress));
- /* PCI does report where the frame buffer address is */
- oldRange = [deviceDescription memoryRangeList];
- numRanges = [deviceDescription numMemoryRanges];
- if (numRanges==3) {
- int ret;
- int i;
-
- /* replace the address */
- for (i=0; i<numRanges; i++) {
- newRange[i] = oldRange[i];
- }
- newRange[0].start = physicalAddress;
- ret = [deviceDescription setMemoryRangeList:newRange num:3];
- if (ret) {
- /* can't set to new memory range */
- IOLog("%s: Can't set memory range, using default.\n",
- [self name]);
- for (i=0; i<numRanges; i++) {
- newRange[i] = oldRange[i];
- }
- physicalAddress = newRange[0].start;
- ret = [deviceDescription setMemoryRangeList:newRange
- num:3];
- if (ret) {
- /* can't set to old range-->major problem! */
- IOLog("%s: Can't set to default range either!\n",
- [self name]);
- return UnknownAdapter;
- }
- }
- } else {
- IOLog("%s: Incorrect number of address ranges: %d.\n",
- [self name], numRanges);
- return UnknownAdapter;
- }
- } else {
- IOLog_dbg(("%s: PCI doesn't tell us the physical address.\n",
- [self name]));
- physicalAddress = [deviceDescription memoryRangeList] -> start;
- configSpace.BaseAddress[0] = physicalAddress;
- [self setPCIConfigSpace:&configSpace];
- }
- return adapterType;
- }
-
-
- /* helper method to -determineEISACardType */
- - (QVAdapterType)adapterTypeFromEISAID:(unsigned int)cardID
- {
- QVAdapterType adapterType;
-
- adapterType = UnknownAdapter;
- IOLog_dbg(("%s: adapterTypeFromEISAID cardID=0x%08x\n", [self name],
- cardID));
- switch (cardID) {
- case QVISION_EISA_ID:
- adapterType = QVisionAdapter;
- break;
- case ORION_EISA_ID:
- adapterType = OrionAdapter;
- break;
- case ORION12_EISA_ID:
- adapterType = Orion12Adapter;
- break;
- case QVISION_ISA_ID:
- case ORION_ISA_ID:
- case ORION12_ISA_ID:
- IOLog("%s: Sorry, ISA cards are not supported (id=0x%08x).\n",
- [self name], cardID);
- break;
- default:
- /* We found some other EISA card. Just ignore it. */
- break;
- }
- return adapterType;
- }
-
- /* helper method to -determineEISACardType */
- - (QVAdapterType)autoScanEISAForCardType
- {
- int slot;
- QVAdapterType adapterType;
- unsigned int cardID;
-
- IOLog_dbg(("%s: doing auto-scan on EISA bus.\n", [self name]));
-
- adapterType = UnknownAdapter;
- for (slot=1; slot<16; slot++) {
- if ([self getEISAId:&cardID forSlot:slot]) {
- adapterType = [self adapterTypeFromEISAID:cardID];
- }
- if (adapterType != UnknownAdapter) {
- IOLog_dbg(("%s: found card in slot %d.\n", [self name], slot));
- return adapterType;
- }
- }
- return UnknownAdapter;
- }
-
- /* can't use atoi() nor sscanf() */
- - (int) getFirstNumber:(char *)s
- {
- char *cptr;
- int n;
-
- cptr = s;
- n = -1;
- while(*cptr && ((*cptr<'0') || (*cptr>'9'))) cptr++;
- while(*cptr && ((*cptr>='0') && (*cptr<='9'))) {
- if (n==-1) n = 0;
- n = n*10 + (*cptr - '0');
- cptr++;
- }
- return n;
- }
-
- /* TODO: clean up error handling, i.e. return something meaningful rather
- * than returning [super free]; */
- - (QVAdapterType) determineEISACardType
- {
- QVAdapterType adapterType;
- int mySlot;
- id deviceDescription;
- const char *slotValue;
- IOConfigTable *configTable;
- unsigned int cardID;
-
- adapterType = UnknownAdapter;
- if (![self isEISAPresent]) {
- IOLog ("%s: Not an EISA system.\n", [self name]);
- return UnknownAdapter;
- }
- deviceDescription = [self deviceDescription];
- configTable = [[self deviceDescription] configTable];
-
- /* see what slot we're supposed be in */
- slotValue = [configTable valueForStringKey:"Location"];
- if (strstr(slotValue, "Slot")) {
- mySlot = [self getFirstNumber:(char *)slotValue];
- IOLog_dbg(("%s: we should be in slot %d\n", [self name], mySlot));
- } else {
- /* instance table doesn't tell us what slot we're in */
- return [self autoScanEISAForCardType];
- }
-
- /* TODO: need to check for auto detect id's */
- if (mySlot > 0) {
- if ([self getEISAId:&cardID forSlot:mySlot]) {
- adapterType = [self adapterTypeFromEISAID:cardID];
- } else {
- /* can't find card in the specified slot, do auto-scan */
- adapterType = [self autoScanEISAForCardType];
- }
- } else {
- /* slot not specified, do auto-scan */
- adapterType = [self autoScanEISAForCardType];
- }
- return adapterType;
- }
-
- - (void)reportConfiguration
- {
- const char *adapterString, *dacString;
-
- switch (adapter) {
- case QVisionAdapter: adapterString = "QVision"; break;
- case OrionAdapter: adapterString = "Orion"; break;
- case Orion12Adapter: adapterString = "Orion12"; break;
- case QVision1280P: adapterString = "QVision1280P"; break;
- default: adapterString = "unknown"; break;
- }
-
- switch (dac) {
- case Bt484: dacString = "Brooktree 484"; break;
- case Bt485: dacString = "Brooktree 485"; break;
- case Bt485A: dacString = "Brooktree 485A"; break;
- case ATT20C505: dacString = "AT&T 20C505"; break;
- default: dacString = "unknown"; break;
- }
-
- IOLog("%s: %s adapter; %s DAC.\n", [self name], adapterString, dacString);
- }
-
- - determineConfiguration
- {
- adapter = UnknownAdapter;
-
- [self determineConfigBusType];
- [self determineDACType];
- switch(busType) {
- case BusISAorVL:
- adapter = [self determineVLCardType];
- break;
- case BusPCI:
- adapter = [self determinePCICardType];
- break;
- case BusEISA:
- adapter = [self determineEISACardType];
- break;
- }
- [self reportConfiguration];
- if (adapter==UnknownAdapter || dac==UnknownDAC) return nil;
- return self;
- }
-
- - selectMode
- {
- int k, mode;
- const QVisionMode *qvMode;
- BOOL validModes[QVisionModeTableCount];
-
- for (k = 0; k < QVisionModeTableCount; k++) {
- qvMode = QVisionModeTable[k].parameters;
- validModes[k] = (qvMode->adapter <= adapter);
- }
-
- mode = [self selectMode:QVisionModeTable count:QVisionModeTableCount
- valid:validModes];
-
- if (mode < 0) {
- IOLog("%s: Sorry, cannot use requested display mode.\n", [self name]);
- switch (adapter) {
- case Orion12Adapter:
- mode = DEFAULT_ORION12_MODE;
- break;
- case OrionAdapter:
- mode = DEFAULT_ORION_MODE;
- break;
- case QVision1280P:
- mode = DEFAULT_1280P_MODE;
- break;
- case QVisionAdapter:
- default:
- mode = DEFAULT_QVISION_MODE;
- break;
- }
- }
- *[self displayInfo] = QVisionModeTable[mode];
- return self;
- }
-
- - initializeMode
- {
- unsigned int i;
- const QVisionMode *mode;
- const IODisplayInfo *displayInfo;
-
- displayInfo = [self displayInfo];
- mode = displayInfo->parameters;
-
- /* Turn off video while setting all of the registers. */
- inb(VGA_INPUT_STATUS_1);
- outb(VGA_ATTR_INDEX, 0x00);
-
- /* Set the sequencer registers. */
- for (i = 0; i < VGA_SEQ_COUNT; i++) {
- outb(VGA_SEQ_INDEX, i);
- outb(VGA_SEQ_DATA, mode->vgaData.seqx[i]);
- }
- outb(VGA_SEQ_INDEX, 0x00);
- outb(VGA_SEQ_DATA, 0x03); /* Restart the sequencer. */
-
- /* Unlock extended graphics registers. */
- outw(VGA_GRFX_INDEX, 0x050f);
-
- /* Unlock more extended registers. */
- outb(VGA_GRFX_INDEX, 0x10);
- outb(VGA_GRFX_DATA, 0x08);
-
- /* Set Advanced VGA mode (set bit 0 of Ctrl Reg 0). */
- outb(VGA_GRFX_INDEX, 0x40);
- outb(VGA_GRFX_DATA, 0x01);
-
- /* Fix sequencer pixel mask for 8 bits. */
- outb(VGA_SEQ_INDEX, SEQ_PIXEL_WR_MSK);
- outb(VGA_SEQ_DATA, 0xff);
-
- outb(CTRL_REG_1, mode->ctrlReg1);
- if (mode->adapter >= OrionAdapter) {
- /* Set access level & enable high address map. */
- outb(QVGA_CTL_2, 0x14);
- /* Select 2 Meg mode. */
- outb(QVGA_CTL_3, 0x05);
- }
-
- /* Set miscellaneous output register. */
- outb(VGA_MISC_OUTPUT, mode->vgaData.miscOutput);
-
- [self programDAC];
-
- /* Load CRTC registers. */
- outb(VGA_CRTC_INDEX, 0x11); /* Unlock CRTC regs 0-7. */
- outb(VGA_CRTC_DATA, 0x00);
- for (i = 0; i < VGA_CRTC_COUNT; i++) {
- outb(VGA_CRTC_INDEX, i);
- outb(VGA_CRTC_DATA, mode->vgaData.crtc[i]);
- }
-
- /* Load overflow registers. */
- outb(VGA_GRFX_INDEX, 0x42);
- outb(VGA_GRFX_DATA, mode->overflow1);
- outb(VGA_GRFX_INDEX, 0x51);
- outb(VGA_GRFX_DATA, mode->overflow2);
-
- /* Load attribute registers. */
-
- inb(VGA_INPUT_STATUS_1); /* Reset latch. */
- for (i = 0; i < VGA_ATTR_COUNT; i++) {
- outb(VGA_ATTR_INDEX, i);
- outb(VGA_ATTR_DATA, mode->vgaData.attr[i]);
- }
-
- /* Load graphics registers. */
- for (i = 0; i < VGA_GRFX_COUNT; i++) {
- outb(VGA_GRFX_INDEX, i);
- outb(VGA_GRFX_DATA, mode->vgaData.grfx[i]);
- }
-
- [self setGammaTable];
-
- /* Re-enable video display. */
- inb(VGA_INPUT_STATUS_1);
- outb(VGA_ATTR_INDEX, 0x20);
-
- return self;
- }
-
- - enableLinearFrameBuffer
- {
- const IODisplayInfo *displayInfo;
- unsigned char tmp;
-
- /* Override the high address map disable, thus allowing access to
- * the high address map of the current board, even when the board
- * is disabled. */
-
- outb(VGA_GRFX_INDEX, HI_ADDR_MAP+1);
- tmp = inb(VGA_GRFX_DATA);
- outb(VGA_GRFX_DATA, tmp | 0x80);
-
- /* Map VRAM. Tell the adapter where to decode the framebuffer. */
-
- /* Set low 8 bits */
- outb(VGA_GRFX_INDEX, HI_ADDR_MAP);
- outb(VGA_GRFX_DATA, (videoRamAddress >> 20) & 0xFF);
-
- /* Set upper 4 bits */
- outb(VGA_GRFX_INDEX, HI_ADDR_MAP + 1);
- outb(VGA_GRFX_DATA, (videoRamAddress >> 28) & 0x0F);
-
- /* Leave them with a nice clear screen. */
-
- displayInfo = [self displayInfo];
- memset(displayInfo->frameBuffer, 0,
- displayInfo->rowBytes * displayInfo->height);
-
- return self;
- }
-
- - resetVGA
- {
- const IODisplayInfo *displayInfo;
- const QVisionMode *mode;
-
- displayInfo = [self displayInfo];
- mode = displayInfo->parameters;
-
- /* Clear the QVision extended mode bit. This is bit 0 of CTRL_REG_1. */
-
- outb(CTRL_REG_1, inb(CTRL_REG_1) & 0xFE);
-
- if (mode != 0 && mode->adapter >= OrionAdapter) {
- /* Select 1 meg mode. */
- outb(QVGA_CTL_3, 0x00);
- /* Reset access level & disable high address map. */
- outb(QVGA_CTL_2, 0x00);
- }
-
- /* Clear the extended 256 color bit. This is bit 0 of 3CF.40. */
- outb(VGA_GRFX_INDEX, 0x40);
- outb(VGA_GRFX_DATA, (inb(VGA_GRFX_DATA) & 0xFE));
-
- /* Clear the page registers - 3CF.45 and 3CF.46. */
- outb(VGA_GRFX_INDEX, PAGE_REG_0);
- outb(VGA_GRFX_DATA, 0x00);
- outb(VGA_GRFX_INDEX, PAGE_REG_1);
- outb(VGA_GRFX_DATA, 0x00);
-
- [self resetDAC];
-
- /* Clear the overflow registers. */
- outb(VGA_GRFX_INDEX, 0x42);
- outb(VGA_GRFX_DATA, 0x00);
- outb(VGA_GRFX_INDEX, 0x51);
- outb(VGA_GRFX_DATA, 0x00);
-
- VGASetMode(0x03);
-
- return self;
- }
- @end
-